﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;

namespace Infrastructure.Domain
{
    [DataContract]
    public class PagingOptions
    {
        [DataMember]
        public string Sort { get; set; }
        [DataMember]
        public int PageSize { get; set; }
        [DataMember]
        public int StartRow { get; set; }
        [DataMember]
        public bool WithPaging { get; set; }
        [DataMember]
        public int TotalRecords { get; set; }

        public string RecordsVerbiage
        {
            get 
            {
                return string.Format("Records {0} to {1} of {2}", StartRow, StartRow + PageSize - 1, TotalRecords);
            }
        }

        public int TotalPages
        {
            get
            {
                if (PageSize == 0)
                    return 0;

                int ret = Convert.ToInt32(Math.Floor(TotalRecords / (Decimal)PageSize));

                if ((TotalRecords % (Decimal)PageSize) != 0)
                    ret += 1;

                return ret;
            }
        }
        public int CurrentPageIndex
        {
            get { return StartRow / PageSize; }
        }

        public int CurrentPageNumber
        {
            get
            {
                return CurrentPageIndex + 1;
            }
        }
        public bool IsFirstPage { get { return CurrentPageIndex == 0; } }
        public bool IsLastPage { get { return CurrentPageIndex == TotalPages; } }
        /// <summary>
        /// prevent "potentially dangerous Request.Form value" error when storing JSON Data
        /// </summary>
        [DataMember]
        public string FilterBackingField { get; set; }
        [DataMember]
        public string Path { get; set; }

        //[IgnoreDataMember()]
        public string Filter
        {
            get
            {
                if (FilterBackingField == null)
                    return null;
                else
                    return Objectifyer.Base64Decode( FilterBackingField );
            }
            set
            {
                if (value == null)
                    FilterBackingField = null;
                else
                    FilterBackingField = Objectifyer.Base64Encode(value);
            }
        }

        public PagingOptions()
        {
            Sort       = null;
            PageSize   = 20;
            StartRow   = 0;
            WithPaging = true;
        }
        public PagingOptions(string sort = null, int pageSize = 0, int startRow = 20, bool withPaging = true)
        {
            Sort       = sort;
            PageSize   = pageSize;
            StartRow   = startRow;
            WithPaging = true;
        }
        public PagingOptions(PagingOptions options)
        {
            if (options == null)
                options = new PagingOptions();

            Sort         = options.Sort;
            PageSize     = options.PageSize;
            StartRow     = options.StartRow;
            WithPaging   = options.WithPaging;
            TotalRecords = options.TotalRecords;
            Filter       = options.Filter;
            Path         = options.Path;
        }
        public static PagingOptions None
        {
            get
            {
                PagingOptions options = new PagingOptions();
                options.WithPaging = false;
                return options;
            }
        }

        public static PagingOptions Default
        {
            get
            {
                PagingOptions options = new PagingOptions();
                return options;
            }
        }
    }

    [DataContract]
    public class PagedList<T> : PagingOptions
    {
        public PagingOptions GetState()
        {
            return new PagingOptions(this);          
        }
        public PagedList()
            : base(Default)
        {
            this.Data = new List<T>();
        }
        public PagedList(PagingOptions options)
            : base(options)
        {
            this.Data = new List<T>();
        }
        [DataMember]
        public IEnumerable<T> Data { get; set; }

        public void Add(T entity)
        {
            if (Data == null)
                Data = new List<T>();
            ((List<T>)Data).Add(entity);
        }

        public void AddRange(IEnumerable<T> list)
        {
            if (Data == null)
                Data = new List<T>();
            ((List<T>)Data).AddRange(list);
        }
        public int Count()
        {
            if (Data == null)
                Data = new List<T>();

            return Data.Count();
        }
    }
}
